#include"Dlish.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
#include<unistd.h>

#define READER_TYPE 1
#define ADMIN_TYPE 0

typedef struct {
    char id[20];  // 图书ID
    char name[40];  // 图书名
    char author[40];  // 作者
    char publisher[40];  // 出版社
    float price;  // 价格
    int stock;  // 库存量

    struct list_head list; // 图书链表
} Book;

typedef struct {
    int type;  // 用户类型，0表示管理员，1表示读者
    char id[20];  // 用户ID
    char name[20];  // 用户名
    char pwd[20];  // 用户密码
    Book *borrowed_books;  // 借阅的图书链表

    struct list_head list; // 用户链表
} User;

//定义全局变量用户列表、图书列表
User *user_head = NULL;
Book *book_head = NULL;

//初始化图书链表
Book *init_book_list(void){
    Book *head = malloc(sizeof(Book));
    if(head != NULL)
        INIT_LIST_HEAD(&head->list);
    return head;
}

// 辅助函数：通过ID查找图书
Book* find_book_by_id(Book *book_head, const char *id) {
    struct list_head *pos;
    list_for_each(pos, &book_head->list) {
        Book *b = list_entry(pos, Book, list);
        if (!strcmp(b->id, id)) return b;
    }
    return NULL;
}

// 辅助函数：通过ID查找用户
User* find_user_by_id(User *user_head, const char *id) {
    struct list_head *pos;
    list_for_each(pos, &user_head->list) {
        User *u = list_entry(pos, User, list);
        if (!strcmp(u->id, id)) return u;
    }
    return NULL;
}

//添加图书
bool add_book_tail(Book *head, char *id, char *name, char *auther, 
    char *publisher, float price, int stock){
        Book *new = malloc(sizeof(Book));
        if(new != NULL){
            strcpy(new->id, id);
            strcpy(new->name, name);
            strcpy(new->author, auther);
            strcpy(new->publisher, publisher);
            new->price = price;
            new->stock = stock;
            list_add_tail(&new->list, &head->list);
            return true;
        }
        return false;
}

//显示图书信息
void show_book_info(const Book *book){
    printf("%s.%s\t%s", book->id, book->name, book->author);
    printf("(%s)\t%.2f元\t%d本\n", book->publisher, book->price, book->stock);
    return;
}

//遍历图书信息
bool book_list_for_each(const Book *head){
    if(head->list.next == &head->list)  //只有一个头节点
        return false;
    struct list_head *pos;
    list_for_each(pos, &head->list){
        Book *data = list_entry(pos, Book, list);
        show_book_info(data);
    }
    return true;
}

//删除图书链表
bool destory_book_list(Book *head){
    if(head != NULL){
        struct list_head *pos, *n;
        list_for_each_safe(pos, n, &head->list){
            Book *book = list_entry(pos, Book, list);
            list_del(pos);
            free(book);
        }
        return true;
    }
    return false;
}

//访客浏览
void show_basic_info(Book *book_head){
    if(book_head == NULL)
        return;
    printf("\n=== 图书基本信息 ===\n");
    struct list_head *pos;
    int i = 0;
    list_for_each(pos, &book_head->list){
        Book *data = list_entry(pos, Book, list);
        printf("%d. %s\t%s (%s)\t%.2f元 - 库存%d本\n", ++i, data->name, data->author,
            data->publisher, data->price, data->stock);
    }
    return;
}

//初始化用户链表
User *init_user_list(void){
    User *head = malloc(sizeof(User));
    if(head != NULL)
        INIT_LIST_HEAD(&head->list);
    return head;
}

//添加用户
bool add_user_tail(User *user_head, int type, char *id, char *name, char *pwd){
    struct list_head *pos;
    list_for_each(pos, &user_head->list){
        User *tmp = list_entry(pos, User, list);
        if(strcmp(tmp->id, id) == 0){
            printf("============>id已存在,");
            return false;
        }
    }
    User *new = malloc(sizeof(User));
    if(new != NULL){
        new->type = type;
        strcpy(new->id, id);
        strcpy(new->name, name);
        strcpy(new->pwd, pwd);
        new->borrowed_books = init_book_list();
        list_add_tail(&new->list, &user_head->list);
        return true;
    }
    return false;
}

//显示用户信息
void show_user_info(const User *user){
    printf("\n=== 读者信息 ===\n");
    printf("id.%s\t读者:%s\n", user->id,user->name);
    printf("在借阅的图书:\n");
    if(!book_list_for_each(user->borrowed_books))
        printf("============>暂无数据\n");
    printf("\n");
    return;
}

//遍历用户信息
void user_list_for_each(const User *head){
    printf("=== 用户信息库 ===\n\n");
    struct list_head *pos;
    list_for_each(pos, &head->list){
        User *data = list_entry(pos, User, list);
        show_user_info(data);
    }
    return;
}

//删除用户
bool del_user(User *head, char *id, User *del_user){
    struct list_head *pos;
    list_for_each(pos, &head->list){
        User *data = list_entry(pos, User, list);
        if(strcmp(id, data->id) == 0){
            list_del(pos);
            if(del_user != NULL){
                del_user->type = data->type;
                strcpy(del_user->id, data->id);
                strcpy(del_user->name, data->name);
                strcpy(del_user->pwd, data->pwd);
                *del_user->borrowed_books = *data->borrowed_books;
            }
            else
                free(list_entry(pos, User, list));
            return true;
        }
    }
    return false;
}

//删除用户链表
bool destory_user_list(User *head){
    if(head != NULL){
        struct list_head *pos, *n;
        list_for_each_safe(pos, n, &head->list){
            User *user = list_entry(pos, User, list);
            list_del(pos);
            free(user);
        }
        return true;
    }
    return false;
}

//用户注册
bool user_register(User *head, int type, char *id, char *name, char *pwd) {
    if (add_user_tail(head, type, id, name, pwd)) {
        FILE *fp = fopen("User.txt", "a+");
        if (fp == NULL) {
            printf("文件打开失败，注册信息未保存到本地！\n");
            return true; // 内存链表已添加成功，仅文件写入失败
        }
        fprintf(fp, "%d %s %s %s\n", type, id, name, pwd);
        fclose(fp);
        return true;
    }
    return false;
}

//用户登录
bool user_login(User *user_head, char *id, char *pwd, User **user){
    struct list_head *pos;
    list_for_each(pos, &user_head->list){
        User *data = list_entry(pos, User, list);
        if(strcmp(data->id, id) == 0 && strcmp(data->pwd, pwd) == 0){
            *user = data;
            printf("============>登录成功!\n");
            return true;
        }
    }
    return false;
}

//显示读者信息
void show_reader_info(User *head){
    if(head != NULL){
        struct list_head *pos, *n;
        list_for_each_safe(pos, n, &head->list){
            User *data = list_entry(pos, User, list);
            if(data->type == 1)
                show_user_info(data);
        }
        return;
    }
}

//借阅统计
void borrow_statistics(){
    struct list_head *upos, *ubpos;
    int flag = 0; //标记是否借过书
    list_for_each(upos, &user_head->list){   //遍历所有用户
        User *user = list_entry(upos, User, list);
        if(user->type == 1 && user->borrowed_books->list.next != &user->borrowed_books->list){//如果用户借了书
            flag = 1;
            printf("%s.%s在借书籍:\n", user->id, user->name);
            list_for_each(ubpos, &user->borrowed_books->list){
                Book *book = list_entry(ubpos, Book, list);
                printf("《%s》\t%s(%s)\t在借%d本\n", book->name, book->author, book->publisher, book->stock);
            }
            printf("\n");
        }
    }
    if(flag == 0)printf("没有读者借过书\n");
}

//更新仓库图书库存
bool update_Book_txt(const char *filename, const char *book_name, int count) {
    FILE *file = fopen(filename, "r+");
    if (!file) return false;
    char buf[256];
    long line_start;
    bool updated = false;
    while (fgets(buf, sizeof(buf), file)) {
        line_start = ftell(file) - strlen(buf); // 记录当前行起始位置
        char id[10], name[100], author[50], publisher[50], price[20];
        int stock;
        // 解析行数据并匹配图书名称
        if (sscanf(buf, "%s %s %s %s %s %d", 
                  id, name, author, publisher, price, &stock) == 6 &&
            strcmp(name, book_name) == 0) {
            // 移动到行首并写入更新后的数据
            fseek(file, line_start, SEEK_SET);
            fprintf(file, "%s %s %s %s %s %d\n", 
                    id, name, author, publisher, price, stock + count);
            updated = true;
            break;
        }
    }
    fclose(file);
    return updated;
}

// 保存所有用户的借阅记录到Bo_book.txt    如果用户借阅书籍数量为0，删除Bo_book中用户
void save_borrowed_books(User *user_head) {
    FILE *fp = fopen("Bo_book.txt", "w"); // 以写入模式打开（覆盖原有内容）
    if (!fp) {
        printf("错误:无法打开借阅记录文件\n");
        return;
    }
    struct list_head *user_pos = NULL;
    // 遍历所有用户
    list_for_each(user_pos, &user_head->list) {
        User *user = list_entry(user_pos, User, list);
        struct list_head *book_pos;
        // int has_borrowed = 0; // 标记用户是否有借阅记录

        // 先检查用户是否有借阅的图书
        if(user->borrowed_books->list.next == &user->borrowed_books->list) continue;
        // list_for_each(book_pos, &user->borrowed_books->list) {
        //     has_borrowed = 1;
        //     break;
        // }
        // if (!has_borrowed) continue; // 无借阅记录则跳过

        // 写入用户ID
        fprintf(fp, "%s ", user->id);
        // 遍历该用户的借阅图书，写入图书ID和数量
        list_for_each(book_pos, &user->borrowed_books->list) {
            Book *borrowed_book = list_entry(book_pos, Book, list);
            fprintf(fp, "%s %d ", borrowed_book->id, borrowed_book->stock);
        }
        fprintf(fp, "\n"); // 每个用户的记录占一行
    }
    fclose(fp);
    printf("============>借阅记录已更新\n");
}

//借阅图书
bool borrow_book(User *user_head, Book *book_head, User *user, char *book_name, int count){
    struct list_head *pos, *n;
    Book *new = malloc(sizeof(Book));
    //遍历书库找到对应图书
    list_for_each_safe(pos, n, &book_head->list){
        Book *book = list_entry(pos, Book, list);
        if(strcmp(book->name, book_name) == 0 && book->stock > 0){//在书库中找到了要借阅的书籍
            list_for_each_safe(pos, n, &user->borrowed_books->list){
                if(strcmp(list_entry(pos, Book, list)->name, book_name) == 0){//判断用户是否借过相同书籍
                    list_entry(pos, Book, list)->stock += count;
                    update_Book_txt("Book.txt", book_name, -count);
                    free(new);
                    save_borrowed_books(user_head);
                    return true;
                }
            }
            if(new == NULL)return false;         //用户没借过相同书籍
            strcpy(new->id, book->id);
            strcpy(new->name, book->name);
            strcpy(new->author, book->author);
            strcpy(new->publisher, book->publisher);
            new->price = book->price;
            new->stock = count;
            update_Book_txt("Book.txt", book_name, -count);
            list_add_tail(&new->list, &user->borrowed_books->list);
            save_borrowed_books(user_head); // 借阅成功后保存记录
            return true;
        }
    }
    return false;
}

//归还图书
void return_book(User *user_head, Book *book_head, User *user, char *book_name, int count){
    if(user == NULL || book_name == NULL || count <= 0){
        printf("============>输入错误!\n");
        return;
    }
    struct list_head *pos, *n;
    //遍历书库找到对应图书
    list_for_each_safe(pos, n, &book_head->list){
        Book *book = list_entry(pos, Book, list);
        if(strcmp(book->name, book_name) == 0){//在书库中找到了要归还的书籍名
            list_for_each_safe(pos, n, &user->borrowed_books->list){
                Book *user_book = list_entry(pos, Book, list);
                //用户借过相同书籍且借阅数量大于等于1且小于等于用户借阅的该书籍数量
                if(strcmp(user_book->name, book_name) == 0 && user_book->stock > 0 &&
                        count <= user_book->stock){
                    user_book->stock -= count;
                    if(user_book->stock == 0){
                        list_del(pos);
                        free(user_book);
                    }
                    update_Book_txt("Book.txt", book_name, count);
                    save_borrowed_books(user_head);
                    printf("============>%d本《%s》归还成功\n", count, book_name);
                    return;
                }
            }
            printf("============>您没有借阅该书籍\n");
            return;  //用户没借
        }
    }
    printf("============>没有找到该书籍\n");
    return;//没找到
}

//借阅记录
void borrow_Record(User *user_head, User *user){
    struct list_head *pos, *n;
     User *data = NULL;
    //遍历用户链表找到对应用户
    list_for_each_safe(pos, n, &user_head->list){
        data = list_entry(pos, User, list);
        if(strcmp(user->id, data->id) == 0)
            break;
    }
    printf("\n用户%s的借阅数据如下:\n", user->name);
    if(!book_list_for_each(user->borrowed_books))
        printf("============>暂无数据\n");
}

//按钮输入格式验证
int button_scanf(int button){
    while(1){
        if(scanf("%d", &button) == 1){  //输入验证
            return button;
        }else{
            char buf[10];
            fgets(buf, 10, stdin);
            printf("输入错误,请重新输入:");
        }
    }
}

//邪修:借助vim打开记事本编辑
bool open_txt_editor(const char *filename) {
    if (!filename || !*filename) return false;
    FILE *fp = fopen(filename, "a+");
    if (!fp) return false;
    fclose(fp);
    char cmd[256];
    snprintf(cmd, sizeof(cmd), "vim \"%s\"", filename);
    return system(cmd) == 0 ? true : false;
}

// 初始化用户借阅记录（从Bo_book.txt加载，支持数量字段）
void init_borrowed_books(User *user_head, Book *book_head) {
    FILE *fp = fopen("Bo_book.txt", "r");
    if (!fp) {
        printf("警告：未找到借阅记录文件\n");
        return;
    }
    char line[256];
    while (fgets(line, sizeof(line), fp)) {
        char *user_id = strtok(line, " \t\n");
        if (!user_id) continue;
        // 查找用户
        User *user = find_user_by_id(user_head, user_id);
        if (!user) continue;
        // 循环读取"书籍ID 数量"对
        char *book_id, *count_str;
        while ((book_id = strtok(NULL, " \t\n")) && (count_str = strtok(NULL, " \t\n"))) {
            int borrow_count = atoi(count_str);
            if (borrow_count <= 0) continue; // 过滤无效数量
            // 查找图书
            Book *book = find_book_by_id(book_head, book_id);
            if (!book) continue;
            // 添加到借阅链表
            Book *borrowed = malloc(sizeof(Book));
            if (borrowed) {
                *borrowed = *book;           // 复制图书基础信息
                borrowed->stock = borrow_count; // 设置实际借阅数量
                list_add_tail(&borrowed->list, &user->borrowed_books->list);
            }
        }
    }
    fclose(fp);
}

//读取User.txt数据
void updata_user_list(char *filename){
    FILE *ufp = fopen(filename, "r");
    if(!ufp){
        printf("============>User.txt不存在!\n");
        return;
    }
    destory_user_list(user_head);
    while(1){
        User user;
        if(fscanf(ufp, "%d %s %s %s", &user.type, user.id, user.name, user.pwd) == EOF)
            break;
        add_user_tail(user_head, user.type, user.id, user.name, user.pwd);
    }
}

//读取Book.txt数据
void updata_book_list(char *filename){
    FILE *bfp = fopen(filename, "r");
    if(!bfp){
        printf("============>Book.txt文件不存在\n");
        return;
    }
    destory_book_list(book_head);
    while(1){
        Book book;
        if(fscanf(bfp, "%s %s %s %s %f %d", book.id, book.name, book.author,
            book.publisher, &book.price, &book.stock) == EOF)
            break;
        add_book_tail(book_head, book.id, book.name, book.author, book.publisher,
            book.price, book.stock);
    }
    fclose(bfp);
}

//管理员菜单
void admin_menu(User *user){
    int button;
    while (1){
        printf("\n\n=== %s ===\n", user->name);
        printf("1.读者信息\n");
        printf("2.图书信息\n");
        printf("3.增删改图书信息\n");
        printf("4.借阅统计\n");
        printf("0.返回上一级菜单\n");
        printf("请选择操作(0-4):");
        button = button_scanf(button);
        printf("\n");
        switch (button){
            case 0:
                return;
            case 1:
                show_reader_info(user_head);  //显示读者信息
                break;
            case 2:
                if(!book_list_for_each(book_head))  //显示图书信息
                    printf("============>暂无数据\n");
                break;
            case 3:
                open_txt_editor("Book.txt");  //增删改书库操作
                updata_book_list("Book.txt");  //更新图书链表
                break;
            case 4:
                borrow_statistics();  //借阅统计:遍历所有用户的借阅链表
                break;
            default:
                printf("============>输入错误,请重新输入\n");
        }
    }
}

//用户菜单
void reader_menu(User *user){
    char name[40];
    int count;
    int button;
    while(1){
        printf("\n\n=== %s ===\n", user->name);
        printf("1.图书浏览\n");
        printf("2.借阅图书\n");
        printf("3.归还图书\n");
        printf("4.借阅记录\n");
        printf("0.返回上一级菜单\n");
        printf("请选择操作(0-4):");
        button = button_scanf(button);
        printf("\n");
        switch (button){
            case 0:
                return;
            case 1:
                if(!book_list_for_each(book_head))      //图书浏览
                    printf("============>暂无数据\n");
                break;
            case 2:
                printf("输入借阅书籍名称:");            //借阅图书
                scanf("%s", name);
                printf("输入借阅书籍数量:");
                scanf("%d", &count);
                if(!borrow_book(user_head, book_head, user, name, count))
                    printf("抱歉，我们还没有上架这本书\n");
                else updata_book_list("Book.txt");
                break;
            case 3:
                printf("输入归还书籍名称:");            //归还图书
                scanf("%s", name);
                printf("输入归还书籍数量:");
                scanf("%d", &count);
                return_book(user_head, book_head, user, name, count);
                break;
            case 4:
                borrow_Record(user_head, user);    //借阅记录
                break;
            default:
                printf("\n============>输入错误,请重新输入!\n");
        }
    }
}

//用户登录
void ulogin(){
    char id[20];
    char pwd[20];
    User *user = NULL;
    int button;
    while (1){
        printf("\n\n=== 登录 ===\n");
        printf("1.管理员登录\n");
        printf("2.读者登录\n");
        printf("0.返回主菜单\n");
        printf("请选择操作(0-2):");
        button = button_scanf(button);
        printf("\n");
        switch(button){
            case 1:
                printf("id账号:");  //输入用户id
                scanf("%s", id);
                printf("密码:");  //输入用户密码
                scanf("%s", pwd);
                if(user_login(user_head, id, pwd, &user) && user->type == 0)  //管理员登录成功读者登录成功
                    admin_menu(user);
                break;
            case 2:
                printf("id账号:");  //输入用户id
                scanf("%s", id);
                printf("密码:");  //输入用户密码
                scanf("%s", pwd);
                if(user_login(user_head, id, pwd, &user) && user->type == 1)  //读者登录成功
                    reader_menu(user);
                break;
            case 0:
                return;
            default:
                printf("============>输入错误，请重新输入\n");
        }
    }
}

//用户注册
void uregister(){
    char id[20];
    char name[20];
    char pwd[20];
    int button;
    while (1){
        printf("\n\n=== 注册 ===\n");
        printf("1.管理员注册\n");
        printf("2.读者注册\n");
        printf("0.返回主菜单\n");
        printf("请选择操作(0-2):");
        button = button_scanf(button);
        printf("\n");
        switch (button){
            case 1:
                printf("输入id:");
                scanf("%s", id);
                printf("输入用户名:");
                scanf("%s", name);
                printf("输入密码");
                scanf("%s", pwd);
                if(user_register(user_head, ADMIN_TYPE, id, name, pwd))
                    printf("============>注册成功!\n");
                else printf("============>注册失败!\n");
                return;
            case 2:
                printf("输入id:");
                scanf("%s", id);
                printf("输入用户名:");
                scanf("%s", name);
                printf("输入密码");
                scanf("%s", pwd);
                if(user_register(user_head, READER_TYPE, id, name, pwd))
                    printf("============>注册成功!\n");
                else printf("============>注册失败!\n");
                return;
            case 0:
                return;
            default:
                printf("============>输入错误!请重新输入!\n");
        }
    }
}

//主菜单
void menu(void){
    while(1){
        printf("\n=== 主菜单 ===\n");
        printf("1.登录\n2.注册\n3.访客浏览(功能未完善)\n0.退出\n");
        printf("请选择操作(0-3):");
        int menu_button;
        menu_button = button_scanf(menu_button);
        printf("\n");
        switch(menu_button){
            case 1:
                ulogin();
                break;
            case 2:
                uregister();
                break;
            case 3:
                show_basic_info(book_head);
                break;
            case 0:
                destory_book_list(book_head);
                destory_user_list(user_head);
                return;
            default:
                printf("\n============>输入错误,请重新输入!\n");
        }
    }
}

int main(int argc, char const *argv[]){
    //初始化数据
    //初始化用户列表、图书列表
    user_head = init_user_list();
    book_head = init_book_list();

    //读取用户数据
    updata_user_list("User.txt");

    //读取图书数据
    updata_book_list("Book.txt");

    //初始化用户借阅数据
    init_borrowed_books(user_head, book_head);

    menu();  // menu(): 对，菜单就是我

    destory_book_list(book_head);
    free(book_head);
    destory_user_list(user_head);
    free(user_head);
}